# Define here the models for your spider middleware
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/spider-middleware.html

from scrapy import signals

# useful for handling different item types with a single interface
from itemadapter import is_item, ItemAdapter

# class BiliSpiderMiddleware:
#     # Not all methods need to be defined. If a method is not defined,
#     # scrapy acts as if the spider middleware does not modify the
#     # passed objects.
#
#     @classmethod
#     def from_crawler(cls, crawler):
#         # This method is used by Scrapy to create your spiders.
#         s = cls()
#         crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
#         return s
#
#     def process_spider_input(self, response, spider):
#         # Called for each response that goes through the spider
#         # middleware and into the spider.
#
#         # Should return None or raise an exception.
#         return None
#
#     def process_spider_output(self, response, result, spider):
#         # Called with the results returned from the Spider, after
#         # it has processed the response.
#
#         # Must return an iterable of Request, or item objects.
#         for i in result:
#             yield i
#
#     def process_spider_exception(self, response, exception, spider):
#         # Called when a spider or process_spider_input() method
#         # (from other spider middleware) raises an exception.
#
#         # Should return either None or an iterable of Request or item objects.
#         pass
#
#     def process_start_requests(self, start_requests, spider):
#         # Called with the start requests of the spider, and works
#         # similarly to the process_spider_output() method, except
#         # that it doesn’t have a response associated.
#
#         # Must return only requests (not items).
#         for r in start_requests:
#             yield r
#
#     def spider_opened(self, spider):
#         spider.logger.info("Spider opened: %s" % spider.name)
#
#
# class BiliDownloaderMiddleware:
#     # Not all methods need to be defined. If a method is not defined,
#     # scrapy acts as if the downloader middleware does not modify the
#     # passed objects.
#
#     @classmethod
#     def from_crawler(cls, crawler):
#         # This method is used by Scrapy to create your spiders.
#         s = cls()
#         crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
#         return s
#
#     def process_request(self, request, spider):
#         # Called for each request that goes through the downloader
#         # middleware.
#
#         # Must either:
#         # - return None: continue processing this request
#         # - or return a Response object
#         # - or return a Request object
#         # - or raise IgnoreRequest: process_exception() methods of
#         #   installed downloader middleware will be called
#         return None
#
#     def process_response(self, request, response, spider):
#         # Called with the response returned from the downloader.
#
#         # Must either;
#         # - return a Response object
#         # - return a Request object
#         # - or raise IgnoreRequest
#         return response
#
#     def process_exception(self, request, exception, spider):
#         # Called when a download handler or a process_request()
#         # (from other downloader middleware) raises an exception.
#
#         # Must either:
#         # - return None: continue processing this exception
#         # - return a Response object: stops process_exception() chain
#         # - return a Request object: stops process_exception() chain
#         pass
#
#     def spider_opened(self, spider):
#         spider.logger.info("Spider opened: %s" % spider.name)
#

import time
import requests
from selenium import webdriver
from selenium.webdriver import ActionChains
from .chaojiying import Chaojiying_Client
import json


class SeleniumDownloaderMiddleware:
    # Not all methods need to be defined. If a method is not defined,
    # scrapy acts as if the downloader middleware does not modify the
    # passed objects.

    @classmethod
    def from_crawler(cls, crawler):
        # This method is used by Scrapy to create your spiders.
        s = cls()
        return s

    def process_request(self, request, spider):
        # Called for each request that goes through the downloader
        # middleware.

        # Must either:
        # - return None: continue processing this request
        # - or return a Response object
        # - or return a Request object
        # - or raise IgnoreRequest: process_exception() methods of
        #   installed downloader middleware will be called
        driver = webdriver.Chrome("D:\download_soft\chromedriver-win64\chromedriver-win64\chromedriver.exe")

        driver.maximize_window()  # 窗口最大化

        url = "https://www.bilibili.com/"
        driver.get(url)  # 打开网页

        # 获取登录节点
        login = driver.find_element_by_class_name("header-login-entry")
        login.click()  # 点击节点

        time.sleep(2)  # 强制等待 2秒钟
        # 获取账户节点
        account = driver.find_element_by_css_selector("div.login-pwd-wp input[type='text']")
        account.send_keys("")  # 输入账户信息

        password = driver.find_element_by_css_selector("div.login-pwd-wp input[type='password']")
        password.send_keys("")  # 输入密码信息

        # 获取登录按钮
        login2 = driver.find_element_by_class_name("btn_primary")
        login2.click()

        time.sleep(2)
        # geetest = driver.find_element_by_class_name("geetest_widget")
        # geetest.screenshot("geetest.png")

        geetest = driver.find_element_by_css_selector("div.geetest_item_wrap")
        background_image = geetest.value_of_css_property("background-image")

        image_url = background_image.replace('url("', '').replace('")', '').split("?")[0]

        # 获取图片内容
        content = requests.get(image_url).content

        with open("geetest.png", "wb") as fp:
            fp.write(content)

        chaojiying = Chaojiying_Client('friendship123', 'asdf1234', '935797')  # 用户中心>>软件ID 生成一个替换 96001
        im = open('geetest.png', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
        pic_str = chaojiying.PostPic(im, 9004)["pic_str"]

        positions = []
        for item in pic_str.split("|"):
            positions.append(item.split(","))

        for position in positions:
            x = int(int(position[0]) * 0.88)
            y = int(int(position[1]) * 0.88)
            ActionChains(driver).move_to_element_with_offset(geetest, x, y).click().perform()
            time.sleep(1)

        # 获取确认节点
        commit = driver.find_element_by_css_selector("div.geetest_commit_tip")
        commit.click()

        time.sleep(2)
        cookies = driver.get_cookies()
        new_cookies = dict()
        for cookie in cookies:
            new_cookies["name"] = cookie["value"]

        request.cookies = new_cookies

        return None

    def process_response(self, request, response, spider):
        # Called with the response returned from the downloader.

        # Must either;
        # - return a Response object
        # - return a Request object
        # - or raise IgnoreRequest
        return response

    def process_exception(self, request, exception, spider):
        # Called when a download handler or a process_request()
        # (from other downloader middleware) raises an exception.

        # Must either:
        # - return None: continue processing this exception
        # - return a Response object: stops process_exception() chain
        # - return a Request object: stops process_exception() chain
        pass
